home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / modelers / geomview / source.lha / Geomview / src / lib / gprim / geom / pick.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-27  |  5.7 KB  |  221 lines

  1. /* Copyright (c) 1992 The Geometry Center; University of Minnesota
  2.    1300 South Second Street;  Minneapolis, MN  55454, USA;
  3.    
  4. This file is part of geomview/OOGL. geomview/OOGL is free software;
  5. you can redistribute it and/or modify it only under the terms given in
  6. the file COPYING, which you should have received along with this file.
  7. This and other related software may be obtained via anonymous ftp from
  8. geom.umn.edu; email: software@geom.umn.edu. */
  9.  
  10. /* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips, 
  11.  * Celeste Fowler */
  12.  
  13. #include "geomclass.h"
  14. #include "pickP.h"
  15.  
  16. #define PICK_POSSIBLE(pick, ap) \
  17. (ap == NULL ? PW_VERT | PW_EDGE | PW_FACE : \
  18.  ((((pick->want & PW_VERT) && \
  19.     (ap->flag & (APF_FACEDRAW | APF_EDGEDRAW | APF_VECTDRAW))) \
  20.    ? PW_VERT : 0) | \
  21.   (((pick->want & PW_EDGE) && \
  22.     (ap->flag & (APF_FACEDRAW | APF_EDGEDRAW | APF_VECTDRAW))) \
  23.    ? PW_EDGE : 0) | \
  24.   (((pick->want & PW_FACE) && \
  25.     (ap->flag & APF_FACEDRAW)) ? PW_FACE : 0))) 
  26.  
  27. int PickFace(int n_verts, Point3 *verts, Pick *pick, Appearance *ap)
  28. {
  29.   Point3 got, ep;
  30.   int v, e;
  31.  
  32.   if (PolyNearPosZInt(n_verts, verts, pick->thresh, &got, &v, &e, &ep) &&
  33.       got.z < pick->got.z && got.z >= -1)
  34.     return PickFillIn(pick, n_verts, &got, v, e, ap);
  35.   else return 0;
  36.  
  37. }
  38.  
  39. int PickFillIn(Pick *pick, int n_verts, Point3 *got, int vertex, 
  40.            int edge, Appearance *ap)
  41. {
  42.   int i, found = 0;
  43.  
  44.   pick->got = *got;
  45.  
  46.   vvcopy(&pick->gcur, &pick->gpath);
  47.  
  48.   found = 0;
  49.   if ((PICK_POSSIBLE(pick, ap) & PW_VERT) && vertex != -1) {
  50.     found |= PW_VERT;
  51.     pick->vi = vertex;
  52.   }
  53.   if ((PICK_POSSIBLE(pick, ap) & PW_EDGE) && edge != -1 ) {
  54.     found |= PW_EDGE;
  55.     pick->ei[0] = edge;
  56.     pick->ei[1] = (edge + 1) % n_verts;
  57.   }
  58.   if (PICK_POSSIBLE(pick, ap) & PW_FACE) {
  59.     found |= PW_FACE;
  60.     pick->fn = n_verts;
  61.   }
  62.   if (found) {
  63.     pick->found = found;
  64.     if (pick->f != NULL) OOGLFree(pick->f);
  65.     pick->f = NULL;
  66.   }
  67.  
  68.   return found;
  69. }
  70.  
  71. Geom *
  72. GeomMousePick(Geom *g, Pick *p, Appearance *ap,
  73.           Transform Tg, double x, double y)
  74. {
  75.     Pick *pick;
  76.     Transform Txy, T;
  77.  
  78.     pick = p ? p : PickSet(NULL, PA_END);
  79.     TmTranslate(Txy, -x, -y, 0.);
  80.     TmConcat(Tg, Txy, T);
  81.     g = GeomPick(g, pick, ap, T);
  82.     if (g && p) {
  83.       TmInvert(p->Tprim, p->Tmirp);
  84.       TmInvert(T, p->Tw);
  85.     }
  86.     if(p == NULL)
  87.     PickDelete(pick);
  88.     return g;
  89. }
  90.  
  91. /*
  92.  * Simple generic Pick routine based on bounding-box intersection.
  93.  * We succeed if the picked point lies within the screen projection of the
  94.  * object, i.e. if the picked point lies within the smallest screen square
  95.  * surrounding the object.  The depth is that of the midpoint of the
  96.  * bounding box: average of min and max depth.
  97.  */
  98. static Geom *
  99. GenericPick(Geom *g, Pick *p, Appearance *ap, Transform T)
  100. {
  101.     Geom *bbox;
  102.     HPoint3 min, max;
  103.  
  104.     bbox = GeomBound(g, T);
  105.     BBoxMinMax(bbox, &min, &max);
  106.     if(min.x <= 0 && max.x >= 0 && min.y <= 0 && max.y >= 0 &&
  107.                     .5*(min.z + max.z) <= p->got.z) {
  108.     p->got.x = p->got.y = 0;
  109.     p->got.z = .5 * (min.z + max.z);
  110.     p->gprim = g;
  111.     TmCopy(T, p->Tprim);
  112.     return g;
  113.     }
  114.     return NULL;
  115. }
  116.  
  117. Geom *
  118. GeomPick(Geom *g, Pick *p, Appearance *ap, Transform T)
  119. {
  120.    if(g == NULL)
  121.     return;
  122.  
  123.    if(g->Class->pick == NULL) {
  124.     /* OOGLError(1, "Note: using GenericPick for class %s",
  125.                 (*g->Class->name)()); */
  126.     g->Class->pick = (GeomPickFunc *)GenericPick;
  127.    }
  128.    return (*g->Class->pick)(g, p, ap, T);
  129. }
  130.  
  131. void
  132. PickDelete(Pick *p)
  133. {    /* Note we don't GeomDelete(p->gprim); it wasn't RefIncr'd */
  134.   if(p) {
  135.     if (p->f) OOGLFree(p->f);    /* free the face list, if any */
  136.     vvfree(&p->gcur);
  137.     vvfree(&p->gpath);
  138.     OOGLFree(p);
  139.   }
  140. }
  141.  
  142. Pick *
  143. PickSet(register Pick *p, int attr, ...)
  144. {
  145.     va_list al;
  146.     int a;
  147.  
  148.     if(p == NULL) {
  149.     /*
  150.      * Create new Pick structure
  151.      */
  152.     p = OOGLNewE(Pick, "new Pick");
  153.     p->got.x = 0;  p->got.y = 0;  p->got.z = 1;
  154.     p->thresh = 0.02;
  155.     p->want = 0;
  156.     p->found = 0;
  157.     VVINIT(p->gcur, int, 1);
  158.     VVINIT(p->gpath, int, 1);
  159.     p->gprim = NULL;
  160.     HPt3From(&p->v, 0.0, 0.0, 0.0, 1.0);
  161.     p->vi = -1;
  162.     HPt3From(&p->e[0], 0.0, 0.0, 0.0, 1.0);
  163.     HPt3From(&p->e[1], 0.0, 0.0, 0.0, 1.0);
  164.     p->ei[0] = -1;
  165.     p->ei[1] = -1;
  166.     p->f = NULL;
  167.     p->fn = 0;
  168.     p->fi = -1;
  169.     }
  170.     va_start(al, attr);
  171.     for(a = attr; a != PA_END; a = va_arg(al, int)) {
  172.     switch(a) {
  173.     case PA_WANT:    p->want = va_arg(al, int); break;
  174.     case PA_THRESH:    p->thresh = va_arg(al, double); break;
  175.     case PA_POINT:    p->got = *va_arg(al, Point3 *); break;
  176.     case PA_DEPTH:    p->got.z = va_arg(al, double); break;
  177.     case PA_GPRIM:    p->gprim = va_arg(al, Geom *); break;
  178.     case PA_TPRIM:  TmCopy(*va_arg(al, Transform *), p->Tprim); break;
  179.     case PA_VERT:    p->v = *va_arg(al, HPoint3 *); break;
  180.     case PA_EDGE: { HPoint3 *e = va_arg(al, HPoint3 *);
  181.             p->e[0] = e[0];
  182.             p->e[1] = e[1];
  183.               }
  184.       break;
  185.     case PA_FACE:    p->f = va_arg(al, HPoint3 *); break;
  186.     case PA_FACEN:    p->fn = va_arg(al, int); break;
  187.     default:
  188.         OOGLError(1, "PickSet: unknown attribute %d", a);
  189.         va_end(al);
  190.         return p;
  191.     }
  192.     }
  193.     va_end(al);
  194.     return p;
  195. }
  196.  
  197. int
  198. PickGet(register Pick *p, int attr, void *attrp)
  199. {
  200.     if(p == NULL)
  201.     return -1;
  202.     switch(attr) {
  203.     case PA_WANT:   *(int *)attrp = p->want; return 1;
  204.     case PA_THRESH: *(float *)attrp = p->thresh; return 1;
  205.     case PA_POINT:  *(Point3 *)attrp = p->got; break;
  206.     case PA_DEPTH:  *(float *)attrp = p->got.z; break;
  207.     case PA_GPRIM:  *(Geom **)attrp = p->gprim; break;
  208.     case PA_TPRIM:  TmCopy(p->Tprim, *(Transform *)attrp); break;
  209.     case PA_VERT: *(HPoint3 *)attrp = p->v; break;
  210.     case PA_EDGE:
  211.       ((HPoint3 *)attrp)[0] = p->e[0];
  212.       ((HPoint3 *)attrp)[1] = p->e[1];
  213.       break;
  214.     case PA_FACE: *(HPoint3 **)attrp = p->f; break;
  215.     case PA_FACEN: *(int *)attrp = p->fn; break;
  216.     default:
  217.     return -1;
  218.     }
  219.     return p->found;
  220. }
  221.